//
//  NcitBleDevice.m
//  BleHrateDemo
//
//  Created by Yongfeng Li on 8/15/14.
//  Copyright (c) 2014 Yongfeng Li. All rights reserved.
//

#import "NcitBleDevice.h"

#define _KgcovLb 2.20462262
#define _kStoredHMUuid @"StoredHMUuid"
#define _kStoredPEUuid @"StoredPEUuid"

@implementation NcitBleDevice {
    BOOL _bJustScanDev;
    
    BOOL _bIsSuptBLe;
    BOOL _bAutoConnect;
    BOOL _bRcvBLeData;
    BOOL _bConnBleDev;
    
    BOOL _bLoadSavedBleDev;
    NSString* _sBleUuid;
    
    id _bleDelegate;
    
    short _nDevType;
    NSString* _sCurtSelUuid;
    //NSString* _sStoredHMUuid;
    //NSString* _sStoredPEUuid;
    
    CBCentralManager*   _bleMgr;
    CBPeripheral*       _pBleDevSvr;
    CBPeripheral*       _pPedoSyncSvr;
    CBCharacteristic*   _pBleDevChar;
    NSMutableArray*     hrConntMonitors;
    
    NSArray* _arSelBleDev;
    NSTimer* _measTimer;
    
    BOOL _bWriteBraceletVal;
    NSDateFormatter* _dtFormat;
    
    BOOL _bBodyMale;
    short _nBodyYear;
    float _fBodyHgt;
    //NSString* _rcvData;
    BOOL _bSyncDevData;
}


/*****************************/
/*    ble strap gague   */
/*****************************/

#pragma mark - BLE init
- (id) initBleDevice
{
    _bJustScanDev = NO;
    
    _bIsSuptBLe = NO;
    _bAutoConnect = YES;
    _bRcvBLeData = NO;
    _bConnBleDev = NO;
    _bLoadSavedBleDev = NO;
    //BLE ini
    hrConntMonitors = [[NSMutableArray alloc] init];
    _bleMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    
    _pBleDevSvr = nil;
    _pPedoSyncSvr = nil;
    _pBleDevChar = nil;
    _arSelBleDev = nil;
    _measTimer = nil;
    
    _dtFormat = [[NSDateFormatter alloc] init];
    //_rcvData = [NSString alloc].init;
    
    _bWriteBraceletVal = NO;
    
    _bBodyMale = NO;
    _nBodyYear = -1;
    _fBodyHgt = 0.0;
    
    _nDevType = 0;
    _sCurtSelUuid = @"";
    //_sStoredHMUuid = @"";
    //_sStoredPEUuid = @"";
    _bSyncDevData = NO;
    
    return self;
}


#pragma mark - BLE center delegate methods
- (BOOL) isLECapableHardware
{
    NSString * state = nil;
    switch ([_bleMgr state])
    {
        case CBCentralManagerStateUnsupported:
            state = @"The platform/hardware doesn't support Bluetooth Low Energy.";
            break;
        case CBCentralManagerStateUnauthorized:
            state = @"The app is not authorized to use Bluetooth Low Energy.";
            break;
        case CBCentralManagerStatePoweredOff:
            state = @"Bluetooth is currently powered off.";
            break;
        case CBCentralManagerStatePoweredOn:
            return TRUE;
        case CBCentralManagerStateUnknown:
        default:
            return FALSE;
            
    }
    
    NSLog(@"Central manager state: %@", state);
    
    /*[self cancelScanSheet:nil];
     NSAlert *alert = [[[NSAlert alloc] init] autorelease];
     [alert setMessageText:state];
     [alert addButtonWithTitle:@"OK"];
     [alert setIcon:[[[NSImage alloc] initWithContentsOfFile:@"AppIcon"] autorelease]];
     [alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:nil contextInfo:nil];*/
    return FALSE;
}

//bluetooth start
- (void) startMeas:(NSString*)sBleUUID
{
    _sBleUuid = sBleUUID;
    _bAutoConnect = YES;
    
    if(!_bIsSuptBLe) {
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleDiscoverFailed)]) {
            [_bleDelegate bleDiscoverFailed];
        }
        return;
    }
    [self stopMeas];
    
    /*NSUInteger nCount = hrConntMonitors.count;
    if(nCount > 0)
        [hrConntMonitors removeAllObjects];*/
    
    _measTimer = [NSTimer scheduledTimerWithTimeInterval:6.00 target:self selector:@selector(onMeasTimer) userInfo:nil repeats:NO];
    NSDictionary *options = @{ CBCentralManagerScanOptionAllowDuplicatesKey: ((_sBleUuid == nil)? @YES: @NO) };
    //[_bleMgr scanForPeripheralsWithServices:nil options:options];
    if(sBleUUID == nil)
        [_bleMgr scanForPeripheralsWithServices:nil options:options];
    else
        [_bleMgr scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:sBleUUID]] options:options];
}

- (void) startScan:(NSString*)sBleUUID
{
    if(_bJustScanDev)
        return;
    
    if(!_bIsSuptBLe) {
        _bIsSuptBLe = [self isLECapableHardware];
        return;
    }
    
    /*[hrConntMonitors removeAllObjects];
    if(_pBleDevSvr != nil) {
        if(![hrConntMonitors containsObject:_pBleDevSvr])
             [hrConntMonitors addObject:_pBleDevSvr];
    }*/
       
    
    _bAutoConnect = NO;
    _measTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(onMeasTimer) userInfo:nil repeats:NO];
    NSDictionary *options = @{ CBCentralManagerScanOptionAllowDuplicatesKey: @NO };//[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber  numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
    
    if(sBleUUID == nil)
        [_bleMgr scanForPeripheralsWithServices:nil options:options];
    else
        [_bleMgr scanForPeripheralsWithServices:[NSArray arrayWithObject:[CBUUID UUIDWithString:sBleUUID]] options:options];
    
    _bJustScanDev = YES;
}

- (void) stopMeas
{
    if(_measTimer != nil) {
        [_measTimer invalidate];
        _measTimer = nil;
    }
    
    if(_pBleDevSvr != nil) {
        [_bleMgr cancelPeripheralConnection:_pBleDevSvr];
        _pBleDevSvr = nil;
        _bConnBleDev = NO;
    }
}

- (void) stopScan
{
    if(!_bIsSuptBLe)
        return;
    /*if(_measTimer != nil) {
        [_measTimer invalidate];
        _measTimer = nil;
    }*/
    [_bleMgr stopScan];
    
    //[self _stopProgressView];
}

- (void) centralManagerDidUpdateState:(CBCentralManager *)central
{
    _bIsSuptBLe = [self isLECapableHardware];
    
    /*if(!_bIsSuptBLe) {
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleDiscoverFailed)]) {
            [_bleDelegate bleDiscoverFailed];
        }
    }*/
    
    if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleSupport:)]) {
        [_bleDelegate bleSupport:_bIsSuptBLe];
    }
    //_btnStart.enabled = _bIsSuptBLe;
}

- (BOOL) IsMatchedPairDev:(NSString*) sDevUuId
{
    BOOL bOK = [_sCurtSelUuid isEqualToString:sDevUuId];
    return bOK;
}

/*
 Invoked when the central discovers blood pressure gague peripheral or other dev while scanning.
 */
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)aPeripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
    if(aPeripheral == nil)
        return;
    
    NSString* sName = aPeripheral.name;
    
    BOOL bSyncDevs = [sName hasPrefix:@"PE"] || [sName hasPrefix:@"OT"] || [sName hasPrefix:@"HW"];;
    BOOL bMatchUuid = [self IsMatchedPairDev:aPeripheral.identifier.UUIDString];
    if(!_bAutoConnect)
        _pBleDevSvr = aPeripheral;
    else if(bSyncDevs && !bMatchUuid)
        return;
    
    BOOL bExists = [hrConntMonitors containsObject:aPeripheral];
    if(!bExists) {
        [hrConntMonitors addObject:aPeripheral];
    }
    
    if(_bAutoConnect && bMatchUuid) {
        _pBleDevSvr = aPeripheral;
        [_bleMgr connectPeripheral:_pBleDevSvr options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
        [self stopScan];
        return;
    }
    else /*if(!bExists)*/ {
        if(_bAutoConnect) {
            //aPeripheral.UUID
            if(sName == nil)
                return;
            
            BOOL bBpDev = [sName isEqual:@"Dual-SPP"] || [sName isEqualToString:@"Bluetooth BP"] || [sName isEqualToString:@"Electronic Scale"]
            ||[sName isEqualToString:@"HjT"] || [sName isEqualToString:@"HNY200KD"] || [sName isEqualToString:@"BOLUTEK"];
            BOOL bBracelet = [sName isEqualToString:@"HW382A"] || [sName isEqualToString:@"HW652"];
            BOOL bYunMai = [sName isEqualToString:@"YUNMAI-JY0002"];
            BOOL bStepMonitor = [sName isEqualToString:@"COOBIT"];
            //BOOL bBpDev = [aPeripheral.identifier isEqual:[CBUUID UUIDWithString:@"FFF1"]] || [aPeripheral.identifier isEqual:[CBUUID UUIDWithString:@"2A51"]];
            if(_sBleUuid != nil || bBpDev || bBracelet || bYunMai || bStepMonitor) {
                _pBleDevSvr = aPeripheral;
                [_bleMgr connectPeripheral:_pBleDevSvr options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                            forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
                //if(bBpDev)
                    [self stopScan];
            }
            if(bBracelet)
                _bWriteBraceletVal = NO;
        }
        [hrConntMonitors addObject:aPeripheral];
    }
    
    if(hrConntMonitors.count > 0) {
        //if(_peripheral == nil || (!_bLoadStoreDevice && [self isLECapableHardware])) {
        if(aPeripheral.state != CBPeripheralStateConnected) { //&& !_bLoadStoreDevice
            //[self loadScanSaverDevices:aPeripheral.identifier.UUIDString];
            if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleMgrDiscover:)]) {
                [_bleDelegate bleMgrDiscover:aPeripheral];
            }
        }
    }
    else {
        //if(_peripheral == nil || (!_bLoadStoreDevice && [self isLECapableHardware])) {
        if(_pBleDevSvr.state != CBPeripheralStateConnected) { //&& !_bLoadStoreDevice
            //[self loadScanSaverDevices:aPeripheral.identifier.UUIDString];
            if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(bleMgrDiscover:)]) {
                [_bleDelegate bleMgrDiscover:aPeripheral];
                
            }
        }
    }
}

/*
 Invoked when the central manager retrieves the list of known peripherals.
 Automatically connect to first known peripheral
 */
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
{
    //if(_bLoadStoreDevice)
    //return;
    NSLog(@"Retrieved peripheral: %u - %@", (int)[peripherals count], peripherals);
    NSUInteger nCount = hrConntMonitors.count;
    if(nCount > 1 && _arSelBleDev == nil) {
        if(!_bAutoConnect)
            [self stopScan];
        if(_pBleDevSvr) {
            [_bleMgr cancelPeripheralConnection:_pBleDevSvr];
            //_peripheral = nil;
        }
        return;
    }
    /* If there are any known devices, automatically connect to it.*/
    //NSUInteger nCount = peripherals.count;
    if([peripherals count] > 0/* && autoConnect*/) {
        //[indicatorButton setHidden:FALSE];
        //[progressIndicator setHidden:FALSE];
        //[progressIndicator startAnimation:self];
        _pBleDevSvr = [peripherals objectAtIndex:0];
        //[_pBleHrateSvr retain];
        [_bleMgr connectPeripheral:_pBleDevSvr options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                        forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
        //_bLoadStoreDevice = YES;
    }
    //else {
    //[self openScanSheet:nil];
    //}
}

/*
 Invoked whenever a connection is succesfully created with the peripheral.
 Discover available services on the peripheral
 */
- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)aPeripheral
{
    [aPeripheral setDelegate:self];
    [aPeripheral discoverServices:nil];
    _pBleDevSvr = aPeripheral;
    
    if (![hrConntMonitors containsObject:aPeripheral])
		[hrConntMonitors addObject:aPeripheral];
    
    NSString* sUuid = aPeripheral.identifier.UUIDString;
    if(_bleDelegate) {
        if([_bleDelegate respondsToSelector:@selector(bleDevConnected)])
            [_bleDelegate bleDevConnected];
        else if([_bleDelegate respondsToSelector:@selector(bleDevConnected:)])
            [_bleDelegate bleDevConnected:sUuid];
    }
    
    //BOOL bYunMai = [aPeripheral.name isEqualToString:@"YUNMAI-JY0002"];
    //if(bYunMai) {
        
    //}
    //if(!bYunMai) {
        [self stopScan];
        _bRcvBLeData = NO;
        _bConnBleDev = YES;
    //}
}

/*
 Invoked whenever an existing connection with the peripheral is torn down.
 Reset local variables
 */
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)aPeripheral error:(NSError *)error
{
    //NSString* sDisconnUuid = aPeripheral.identifier.UUIDString;
    //if(![sDisconnUuid isEqualToString:_sBleUuid])
        //return;
    
    /*CBPeripheral* service = nil;
    for (service in hrConntMonitors) {
        if (service == aPeripheral) {
            [hrConntMonitors removeObject:service];
            break;
        }
    }*/
    if(_pBleDevSvr != nil) {
        [_bleMgr cancelPeripheralConnection:_pBleDevSvr];
        _pBleDevSvr = nil;
    }
    [self stopMeas];
    //[self startScan];
    
    if(_bleDelegate  && [_bleDelegate respondsToSelector:@selector(bleDisconnected)]) {
        [_bleDelegate bleDisconnected];
    }
    if([_sBleUuid isEqualToString:@"180D"])
        [self startMeas:@"180D"];
}

/*
 Invoked whenever the central manager fails to create a connection with the peripheral.
 */
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)aPeripheral error:(NSError *)error
{
    NSLog(@"Fail to connect to peripheral: %@ with error = %@", aPeripheral, [error localizedDescription]);
    //[connectButton setTitle:@"Connect"];
    if( _pBleDevSvr != nil && _pBleDevSvr == aPeripheral)
    {
        [_pBleDevSvr setDelegate:nil];
        //[_pBleHrateSvr release];
        _pBleDevSvr = nil;
    }
    //_lblState.text = [NSString stringWithFormat: @"%@ %s", [aPeripheral name], "Fail to connect"];
}

- (void) centralManager:(CBCentralManager *)central didFailToRetrievePeripheralForUUID:(CFUUIDRef)UUID error:(NSError *)error
{
	/* Nuke from plist. */
	//[self removeSavedDevice:UUID];
}

#pragma mark - CBPeripheral delegate methods
/*
 Invoked upon completion of a -[discoverServices:] request.
 Discover available characteristics on interested services
 */
- (void) peripheral:(CBPeripheral *)aPeripheral didDiscoverServices:(NSError *)error
{
    for (CBService *aService in aPeripheral.services)
    {
        //NSLog(@"Service found with UUID: %@", aService.UUID);
        //lblMsg.text = [NSString stringWithFormat:@"%@", aService.UUID];
        NSString* sBleName = aService.peripheral.name;
        NSString* sUuidStr = aService.UUID.UUIDString;
        
        BOOL bBlDev = [aService.UUID isEqual:[CBUUID UUIDWithString:@"FC00"]] || [sBleName isEqualToString:@"HW652"];
        BOOL bHrDev = [aService.UUID isEqual:[CBUUID UUIDWithString:@"180D"]];
        BOOL bBpDev = [aService.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]];
        BOOL bPedoDev = [sBleName hasPrefix:@"PE"];
        
        BOOL bSyncDev = [sBleName hasPrefix:@"OT"] && ![sBleName hasPrefix:@"AC"] && ![sBleName hasSuffix:@"HRM"];
        if(bSyncDev || bBlDev || bPedoDev) {
            [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FC20"],
                                                  [CBUUID UUIDWithString:@"FC21"],
                                                   [CBUUID UUIDWithString:@"FC22"]] forService:aService];
        }
        else if (bHrDev) {
            //lblMsg.text = NSLocalizedString(@"kQuiet", nil);
            [aPeripheral discoverCharacteristics:nil forService:aService];
            //txtData.text = [NSString stringWithFormat: @"%@ %s", [[aService peripheral] name], "found"];//@"Heart Rate Service found";
        }
        else if (bBpDev) {
            [aPeripheral discoverCharacteristics:nil forService:aService];
        }
        else if([aService.UUID isEqual:[CBUUID UUIDWithString:@"180F"]]) {
            //lblMsg.text = @"battery";
            [aPeripheral discoverCharacteristics:nil forService:aService];
        }
        else {
            if ([aService.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]] || [sBleName isEqualToString:@"Electronic Scale"]) {
                [aPeripheral discoverCharacteristics:nil forService:aService];
            }
            else if ([sBleName isEqualToString:@"HNY200KD"]) {
                [aPeripheral discoverCharacteristics:nil forService:aService];
            }
            else if ([sBleName isEqualToString:@"HjT"] || [sBleName isEqualToString:@"HNY200KD"] || [sBleName isEqualToString:@"BOLUTEK"] || [aService.UUID isEqual:[CBUUID UUIDWithString:@"FFE0"]]) {
                
                if([sBleName isEqualToString:@"YUNMAI-JY0002"]) { // new Accuro Ble svale
                    //[aPeripheral discoverCharacteristics:nil forService:aService];
                    [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FFE4"],[CBUUID UUIDWithString:@"FFE5"]] forService:aService];
                    /*if([sUuidStr isEqualToString:@"FFE5"]) { //yunmai accuro scale write
                        _pBleDevSvr = aPeripheral;
                        for (CBCharacteristic *aChar in aService.characteristics) {
                            if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToYunmaiBLeDev:)])
                                [_bleDelegate sendDataToYunmaiBLeDev:aChar];
                        }
                    }*/
                }
                else {
                    [aPeripheral discoverCharacteristics:nil forService:aService];
                }
            }
            else if([sUuidStr isEqualToString:@"FFE5"]) {
                [aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FFE9"]] forService:aService];
                /*if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToYunmaiBLeDev:)]) {
                    if(aService.characteristics.count > 0) {
                        CBCharacteristic *aChar = aService.characteristics[0];
                        [_bleDelegate sendDataToYunmaiBLeDev:aChar];
                    }
                }*/
                
            }
        }
        
    }
}

/*
 Invoked upon completion of a -[discoverCharacteristics:forService:] request.
 Perform appropriate operations on interested characteristics
 */
- (void) peripheral:(CBPeripheral *)aPeripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    //write to peripheral
    //NSString* sUuidStr = service.UUID.UUIDString;
    //BOOL bHrDev = [sUuidStr hasPrefix:@"180"];
    BOOL bBldDevFound = NO;
    
    /*for (CBCharacteristic *characteristic in service.characteristics) {
        NSLog(@"Discovered characteristic %@", characteristic);
    }*/
    
    if([service.UUID isEqual:[CBUUID UUIDWithString:@"FC00"]]) { //bracelet
        for (CBCharacteristic *aChar in service.characteristics) {
               /*if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToPedoDev:)]) {
                    [_bleDelegate sendDataToPedoDev:aChar];
                }
            }
            else */if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]]) {
                //[aPeripheral readValueForCharacteristic:aChar];
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
                _pPedoSyncSvr = aPeripheral;
            }
            else if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC22"]]) {
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
            }
            else if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC21"]]) {
                //[_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar]; //for BldMeas
                _pBleDevChar = aChar;
                _bConnBleDev = YES;
                
                //NSLog(@"Dscover char point: %@", _pBleDevChar);
               //test send data package this time
                /*uint8_t val[4] = {0xE0, 0x00, 0x00, 0xE0};
                NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
                [_pBleDevSvr writeValue:valData forCharacteristic:_pBleDevChar type:CBCharacteristicWriteWithResponse];*/
            }
        }
    }
    else if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]]) {
        for (CBCharacteristic *aChar in service.characteristics) {
            
            if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF4"]]) {
                 [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
            }
            else if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF1"]]) {
                bBldDevFound = YES;
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar]; //for BldMeas
                //[self sendDataToBleDev:aChar];//send data to scale
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToBleDev:)]) {
                    [_bleDelegate sendDataToBleDev:aChar];
                }
            }
             else if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF2"]]) { //write
                  _pBleDevChar = aChar;
             }
        }
    }
    else  if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFE0"]]) {
        for (CBCharacteristic *aChar in service.characteristics) {
            if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]]) {
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
                //NSLog(@"Found a BLE Electronic Scale Measurement Characteristic");
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToBleDev:)])
                    [_bleDelegate sendDataToBleDev:aChar];
            }
            else if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE4"]]) { //yunmai accuro scale read
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
                //[aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:@"FFE5"]] forService:service];
            }
            else if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE9"]]) { //yunmai accuro scale write
                _pBleDevSvr = aPeripheral;
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToYunmaiBLeDev:)])
                    [_bleDelegate sendDataToYunmaiBLeDev:aChar];
            }
        }
    }
    else  if ([service.UUID isEqual:[CBUUID UUIDWithString:@"FFE5"]]) { //yumai oth service
         _pBleDevSvr = aPeripheral;
        aPeripheral.delegate = self;
        for (CBCharacteristic *aChar in service.characteristics) {
            if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFE9"]]) { //yunmai accuro scale write
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToYunmaiBLeDev:)])
                    [_bleDelegate sendDataToYunmaiBLeDev:aChar];
            }
        }
    }
    
    //bld meas, write to peripheral
    BOOL bBpDev = [service.UUID isEqual:[CBUUID UUIDWithString:@"FFF0"]] || [service.UUID isEqual:[CBUUID UUIDWithString:@"1810"]];
    if (!bBldDevFound && bBpDev) {
        for (CBCharacteristic *aChar in service.characteristics) {
            bBpDev = [aChar.UUID isEqual:[CBUUID UUIDWithString:@"FFF2"]];
            if(bBpDev) {
                _pBleDevChar = aChar;
                _bConnBleDev = YES;
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(sendDataToBleDev:)]) {
                    [_bleDelegate sendDataToBleDev:aChar];
                }
                return;
            }
        }
    }
    
    if ([service.UUID isEqual:[CBUUID UUIDWithString:@"180D"]]) {
        //NSLog(@"service UUID:%@", service.UUID);
        for (CBCharacteristic *aChar in service.characteristics) {
            // Set notification on heart rate measurement
            if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"2A37"]])
            {
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
                NSLog(@"Found a Heart Rate Measurement Characteristic");
            }
            
            //sync data
            if([aChar.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]]) {
                //[aPeripheral readValueForCharacteristic:aChar];
                [_pBleDevSvr setNotifyValue:YES forCharacteristic:aChar];
            }

            //NSLog(@"service UUID:%@", aChar.UUID);
        }
    }
    
    if ([service.UUID isEqual:[CBUUID UUIDWithString:@"180A"]]) {
        for (CBCharacteristic *aChar in service.characteristics) {
            /* Read manufacturer name */
            if ([aChar.UUID isEqual:[CBUUID UUIDWithString:@"2A29"]]) {
                [aPeripheral readValueForCharacteristic:aChar];
                //NSLog(@"Found a Device Manufacturer Name Characteristic");
            }
        }
    }
    
    //battery lever
    if([service.UUID isEqual:[CBUUID UUIDWithString:@"180F"]]) {
        for (CBCharacteristic *characteristic in service.characteristics) {
            //NSLog(@"discovered characteristic %@", characteristic.UUID);
            if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A19"]]) {
                [aPeripheral readValueForCharacteristic:characteristic];
                //[aPeripheral setNotifyValue:YES forCharacteristic:characteristic];
                //NSLog(@"Found Notify Characteristic %@", characteristic);
                //NSLog(@"value:%@",characteristic.value);
            }
        }
    }
    
}


/*
 Invoked upon completion of a -[readValueForCharacteristic:] request or on the reception of a notification/indication.
 */
- (double) getBleWgtData:(NSData*)data fat:(float*) fFat wat:(float*)fWat wgt:(short*)nWgt wUnit:(short*)nUn fatwatInc:(BOOL*)bFatWat hgt:(float*)fHgt
{
    uint8_t bWgth, bWgtl;
    const uint8_t *reportData = [data bytes];
    uint8_t bStart = reportData[0];
    //if(bStart == 0xfd)
    //return 0.0;
    
    *bFatWat = NO;
    float dFatVal = 0.0f, dWatVal = 0.0f;
    if(bStart == 0xCf) {
        *fHgt = reportData[3] / 100.0;
        
        bWgth = reportData[4];
        bWgtl = reportData[5];
        
        uint8_t bFath = reportData[6];
        uint8_t bFatl = reportData[7];
        dFatVal = ((bFath << 8) + bFatl) / 10.0;
        
        uint8_t bWath = reportData[12];
        uint8_t bWatl = reportData[13];
        dWatVal = ((bWath << 8) + bWatl) / 10.0;
        
        if(dFatVal == 0 && dWatVal == 0)
            *bFatWat = NO;
        else
            *bFatWat = YES;
    }
    else {
        bWgth = reportData[2];
        bWgtl = reportData[3];
        //glass ble scale
        if(bWgtl == 0 && bWgth == 0) {
            bWgth = reportData[4];
            bWgtl = reportData[5];
        }
    }
    
    short nWgtVal = ((bWgth << 8) + bWgtl);
    //float fWgtVal = _nLastWgtVal / 10.0;
    double dWgtVal = nWgtVal / 10.0;
    
    *nWgt = nWgtVal;
    *nUn = 1; //1: kg, 2: lb
    
    *fFat = dFatVal;
    *fWat = dWatVal;
    
    return dWgtVal;
}

-(NSString *)getUTCFormateDate:(NSDate *)localDate
{
    //NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
    NSTimeZone *timeZone = [NSTimeZone localTimeZone];
    [_dtFormat setTimeZone:timeZone];
    [_dtFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    //[_dtFormat setDateFormat:@"MM"];
    //int month = [[_dtFormat stringFromDate:[NSDate date]] intValue];
    NSString *dateString = [_dtFormat stringFromDate:localDate];
    //[_dtFormat release];
    return dateString;
}

- (void) recvBraceLetData:(const uint8_t *)rcvData len:(NSUInteger)nDataLen char:(CBCharacteristic*)bleChar
{
    /*if(nDataLen == 6) {
        NSString* sData = [NSString stringWithFormat:@"UTC Length: %li-> %@", (long)nDataLen, characteristic.value.description];
        [_bleDelegate recvedBleOthData:sData];
    }*/
    
    uint8_t _nBraceletIdx = (rcvData[0] & 0xf0) >> 4;
    uint8_t _nBraceletCmd = rcvData[0] & 0x0f;
    if(! _bWriteBraceletVal && nDataLen == 17 && _nBraceletCmd == 0x01) {

        float fWgt = ((rcvData[7] << 8) + rcvData[8]) / 10.0;
        Byte nAge = rcvData[9];
        Byte nHgt = rcvData[10];
        Byte nSex = rcvData[12];
        [_bleDelegate recvedBleOthData:[NSString stringWithFormat:@"wgt:%.1f kg, Age:%i, Hgt:%i cm Sex: %@", fWgt, nAge, nHgt, ((nSex==0)?@"Female":@"Male")]];
        
        [NSThread sleepForTimeInterval:0.5];
        if(_pBleDevSvr != nil && _pBleDevChar != nil) {
            uint8_t val[4] = {0xE0, 0x00, 0x00, 0xE0};
            val[1] = _nBraceletIdx;
            val[3] += _nBraceletIdx;
            NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
            [_pBleDevSvr writeValue:valData forCharacteristic:_pBleDevChar type:CBCharacteristicWriteWithResponse];
            //[_pBleDevSvr writeValue:valData forCharacteristic:bleChar type:CBCharacteristicWriteWithoutResponse];
            
            _bWriteBraceletVal = YES;
        }
        
    }
    else if(nDataLen == 6) {
        NSString* sData = [NSString stringWithFormat:@"%li bytes: %02X %02X %02X %02X %02X %02X", (long)nDataLen, rcvData[0], rcvData[1], rcvData[2], rcvData[3], rcvData[4], rcvData[5]];
        [_bleDelegate recvedBleOthData:sData];
        if(_nBraceletCmd == 0x0 ) {
            uint8_t val[4] = {0xE0, 0x00, 0x01, 0xE1};
            //val[1] = _nBraceletIdx;
            //val[3] += _nBraceletIdx;
            NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
            [self sendDataToBleDev:_pBleDevChar data:valData type:CBCharacteristicWriteWithResponse];
        }
        
    }
    else if(nDataLen == 15) { //fitness info
        int nSteps = (rcvData[5] >> 16) + (rcvData[6] >> 8) + rcvData[7];
        int nDists = (rcvData[8] >> 16) + (rcvData[9] >> 8) + rcvData[10];
        int nCalor =  (rcvData[11] >> 16) + (rcvData[12] >> 8) + rcvData[13];
        NSString* sInfo = [NSString stringWithFormat:@"steps:%i, Dists:%i, Calo:%i", nSteps, nDists, nCalor];
        [_bleDelegate recvedBleOthData:sInfo];
        
        uint8_t val[4] = {0xE0, 0x02, 0x00, 0xE2};
        //val[1] = _nBraceletIdx;
        //val[3] += _nBraceletIdx;
        NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
        [self sendDataToBleDev:_pBleDevChar data:valData type:CBCharacteristicWriteWithResponse];
        
    }
    else if(nDataLen == 20) {
        NSString* sInfo = @"data package leng 20, beging details";
        [_bleDelegate recvedBleOthData:sInfo];
        
    }
    else if(nDataLen == 4) {
        Byte nIdx = (rcvData[0] & 0xf0) >> 4;
        Byte nCom = rcvData[0] & 0x0f;
        BOOL bEnd = rcvData[1] == 0x03;
        Byte nPackLen = rcvData[2];
        
        NSString* sEnd = @"";
        NSString* sInfo = [NSString stringWithFormat:@"Recv package(4): idx:%i, com:%i", nIdx, nCom];
        if(bEnd) {
            sEnd = [NSString stringWithFormat:@". End len: %i", nPackLen];
        }
        
        NSMutableString* sInfos = [NSMutableString stringWithFormat:sInfo, sEnd];
        [_bleDelegate recvedBleOthData:sInfos];
        
    }
    else {
        //NSString* sInfo = [NSString stringWithFormat: @"other data received: %ld", (long)nDataLen];
        //[_bleDelegate recvedBleOthData:sInfo];
        
        NSString* sData = [NSString stringWithFormat:@"UTC Length: %li-> %@", (long)nDataLen, bleChar.value.description];
        [_bleDelegate recvedBleOthData:sData];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    //NSString* sUuid = characteristic.UUID.UUIDString;
    if (error) {
        //NSLog(@"Error changing notification state: %@", error.localizedDescription);
    }
    
    // Notification has started
    if (characteristic.isNotifying) {
        //NSLog(@"Notification began on %@", characteristic);
    }
}

- (void) peripheral:(CBPeripheral *)aPeripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    //NSLog(@"UUID: %@", characteristic.UUID);
    NSString* sBleName = @"";
    //NSString* sCharUuid = characteristic.UUID.UUIDString;
    for (CBService *aService in aPeripheral.services) {
        sBleName = aService.peripheral.name;
    }

    BOOL bBracelet = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]];
    if(!bBracelet)
        bBracelet = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FC00"]];
    BOOL bYunMai = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE4"]] && [sBleName isEqualToString:@"YUNMAI-JY0002"];
    BOOL bBleScale = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF4"]];
    if(!bBleScale)
        bBleScale = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFE1"]];
    
    BOOL bHrDev = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A37"]];// || [sCharUuid isEqualToString:@"2A19"];
    if(!_bSyncDevData  && !bHrDev)
        bHrDev = [sBleName hasPrefix:@"AC"] || [sBleName hasPrefix:@"OT"] || [sBleName hasSuffix:@"HRM"];
    BOOL bBpDev = [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FFF1"]] || [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A51"]];
    BOOL bPedoDev = [sBleName hasPrefix:@"PE"];//sBleName isEqualToString:@"COOBIT"];;
    
    if(bHrDev) {
        bBracelet = NO;
        bPedoDev = NO;
    }
    NSUInteger nDataLen = characteristic.value.length;
    const uint8_t *rcvData = [characteristic.value bytes];
    
    //battery level
    if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A19"]]) {
        //NSLog(@"Found Notify Characteristic %@", characteristic);
        //NSLog(@"value:%@",characteristic.value);
        const uint8_t *reportData = [characteristic.value bytes];
        uint8_t val = reportData[0];
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(updateBatteryLevel:)]) {
            [_bleDelegate updateBatteryLevel:val];
        }
    }
    
    if(bYunMai) {
        int nIdx = 6;
        float fWgtKg = 0;
        float fWgtVal = 0.0;
        short nUn = 2;
        if(nDataLen == 0x11) {
            nIdx = 11;
            uint8_t val[2] = {0x02, 0x94};
            NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
            [_pBleDevSvr writeValue:valData forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
            
            //uint8_t nLen = rcvData[0];
            //uint8_t nCmdNo = rcvData[1];
            
            uint8_t hWgt = rcvData[nIdx];
            uint8_t lWgt = rcvData[nIdx + 1];
            short nWgt = (hWgt << 8) + lWgt;
            fWgtKg = nWgt / 100.0;
            fWgtVal = fWgtKg * _KgcovLb;//2.20462262;
            
            
            /*uint8_t hRes = rcvData[13];
            uint8_t lRes = rcvData[14];
            float fRes = ((hRes << 8) + lRes);*/
            
            uint8_t hFat = rcvData[15];
            uint8_t lFat = rcvData[16];
            float fFat = ((hFat << 8) + lFat) / 100.0;
            
            //aater
            float fWat = (100.0 -  fFat)  * 11.0 / 16.0; //0.73;
            //musele & bone
            float fMus = (fWat * 61 + 1600 + 2 * fWgtKg - _fBodyHgt) / 100.0 - (_bBodyMale? 4: 0);
            float fBone = (float)(fFat * 103.0 + fWat *  312.0 + fWgtKg * 237.0 + _fBodyHgt * 237.0 - 154170.0 - 49.0 * _nBodyYear - 246.0 * fMus) / 10000.0f + 13.0f;
            fBone = fabsf(fBone) * _KgcovLb;;
            if(fFat == 0.0) {
                fWat = 0.0f;
                fMus = 0.0f;
                fBone = 0.0f;
            }
            
            [_bleDelegate recvedBleWgtData:fWgtVal fat:fFat wat:fWat mus:fMus bone:fBone wUnit:nUn fatwatInc:YES hgt:_fBodyHgt];
        }
    }
    else if(bBracelet || bPedoDev) {
        if( (characteristic.value)  || !error ) {
            // Update UI with heart rate data
            //if(_bRcvBLeData)
                //return;
            if(/*!_bLoadSavedBleDev && */[characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]]) {
                if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleDevSyncData: len: char:)]) {
                    [_bleDelegate recvedBleDevSyncData: rcvData len: nDataLen char: _pBleDevChar];
                    //[_pBleDevSvr setNotifyValue:YES forCharacteristic:characteristic];
                }
            }
            else if([CBUUID UUIDWithString:@"FC22"]) {
                if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBlePedoStepData: len:)]) {
                    [_bleDelegate recvedBlePedoStepData: rcvData len: nDataLen];
                    //[_pBleDevSvr setNotifyValue:YES forCharacteristic:characteristic];
                }
            }
            
            /*else if (if([CBUUID UUIDWithString:@"FC22"]) {) {
                    if(bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleOthData:)]) {
                //NSString* sData = [_rcvData initWithData:characteristic.value encoding:NSASCIIStringEncoding];
                //[_bleDelegate recvedBleOthData:sData];
                //[_bleDelegate recvedBleOthData:characteristic.value.description];
                        [self recvBraceLetData: rcvData len: nDataLen char: characteristic];
                //[_pBleDevSvr setNotifyValue:YES forCharacteristic:characteristic];
            }*/
        }
    
    }
    else if (bBleScale) {
        if( (characteristic.value)  || !error ) {
            // Update UI with heart rate data
            if(_bRcvBLeData)
                return;
            NSUInteger nDataLen = characteristic.value.length;
            const uint8_t *rcvData = [characteristic.value bytes];
            
            BOOL bNuyuWgt = nDataLen == 9 ||  nDataLen == 12;
            
            //if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleWgtData:)]) {
            if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleWgtData:fat:wat:mus:bone:wUnit:fatwatInc:hgt:)]) {
                if(bNuyuWgt) {
                    if(rcvData[0] == 'N' && rcvData[1] == 'U' && rcvData[2] == 'Y' && rcvData[3] == 'U' && rcvData[4] == 'W') {
                        uint8_t bWgth = rcvData[5];
                        uint8_t bWgtl = rcvData[6];
                        uint8_t nUn = rcvData[7];
                        //glass ble scale
                        if(bWgtl == 0 && bWgth == 0) {
                            return;
                        }
                        short nWgtVal = ((bWgth << 8) + bWgtl);
                        float fWgtVal = nWgtVal / 10.0;
                        
                        UInt8 nVer = 1;
                        if (nDataLen > 10) {
                            nVer = rcvData[10];
                            //UInt8 e = rcvData[11];
                        }
                        //if(nUn == 1)
                            //nWgtVal *= 0.45359237;
                        
                        [_bleDelegate recvedBleWgtData:fWgtVal fat:0.0f wat:0.0f mus:0.0f bone:0.0f wUnit:nUn fatwatInc:NO hgt:0.0];
                        //[_bleDelegate recvedBleWgtData:fWgtVal unit: nUn ver: nVer];
                    }
                    
                }
                else {
                    BOOL bIncFwat;
                    short nWgtVal, nWunit;
                    float fFatVal, fWatVal, fHgt;
                    double dWgtVal = [self getBleWgtData:characteristic.value fat:&fFatVal wat:&fWatVal wgt:&nWgtVal wUnit:&nWunit fatwatInc:&bIncFwat hgt:&fHgt];
                    [_bleDelegate recvedBleWgtData:dWgtVal fat:fFatVal wat:fWatVal mus:0.0f bone:0.0f wUnit:nWunit fatwatInc:bIncFwat hgt:fHgt];
                    //[_bleDelegate recvedBleWgtData:characteristic.value];
                }
            }
            
            return;
        }
    }
    else if (bHrDev) {
        if( (characteristic.value)  || !error ) {
            /* Update UI with heart rate data */
            //if(_bRcvBLeData)
            //return;
            
            NSData* data = characteristic.value;
            const uint8_t *reportData = [data bytes];
            uint16_t bpm = 0;
            
            if ((reportData[0] & 0x01) == 0) {
                /* uint8 bpm */
                bpm = reportData[1];
            }
            else {
                /* uint16 bpm */
                bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
            }
            if(bpm > 255)
                 bpm = reportData[1];
            //self.heartRate = bpm;
            //[self showPulseData:(short)bpm];
            if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedHrateData:)]) {
                [_bleDelegate recvedHrateData:bpm];
            }
            
            /*if(_bleDelegate && [characteristic.UUID isEqual:[CBUUID UUIDWithString:@"FC20"]]) {
                if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleDevSyncData: len: char:)]) {
                    [_bleDelegate recvedBleDevSyncData: rcvData len: nDataLen char: _pBleDevChar];
                    //[_pBleDevSvr setNotifyValue:YES forCharacteristic:characteristic];
                }
            }*/
            
            return;
        }
    }
    else if (bBpDev) {
        if( (characteristic.value)  || !error ) {
            NSData* data = characteristic.value;
            NSUInteger nLen = data.length;
            const uint8_t* bRcvData = [data bytes];
            BOOL bRecvPres = nLen == 7;
            if(nLen == 1 && bRcvData[0] == 0xA5 && _pBleDevSvr != nil && _pBleDevChar != nil) {
                uint8_t val[6] = {0xFD, 0xFD, 0xFA, 0x05, 0x0D, 0x0A};
                NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
                [_pBleDevSvr writeValue:valData forCharacteristic:_pBleDevChar type:CBCharacteristicWriteWithResponse];
            }
            else if(data.length == 5 && bRcvData[2] == 0x06) { //begin to meas
                //_bNeedStored = YES;
                _bConnBleDev = YES;
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(beginMeasBldPre)]) {
                    [_bleDelegate beginMeasBldPre];
                }
                //_btnStart.enabled = NO;//!_btnStart.enabled;
                //_btnTurnoff.enabled = !_btnStart.enabled;
            }
            else if(bRecvPres && bRcvData[2] == 0xFB) {
                short nPresVal = bRcvData[3] * 256 + bRcvData[4];
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(updateBldPreVal:)]) {
                    [_bleDelegate updateBldPreVal:nPresVal];
                }
                //[_vBldPres setPresVal:nPresVal];
                //_lblInfo.text = [NSString stringWithFormat:@"Measuring: %d", nPresVal];
            }
            else if(data.length == 8 && bRcvData[2] == 0xFC) { //meas end
                Byte nhPres = bRcvData[3];
                Byte nlPres = bRcvData[4];
                Byte nhRate = bRcvData[5];
                
                if(_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBldPreVal:lPres:hRate:)]) {
                    [_bleDelegate recvedBldPreVal:nhPres lPres: nlPres hRate:nhRate];
                }
                
                //close
                uint8_t val[6] = {0xFD, 0xFD, 0xFE, 0x06, 0x0D, 0x0A};
                NSData* valData = [NSData dataWithBytes:(void*)&val length:sizeof(val)];
                [_pBleDevSvr writeValue:valData forCharacteristic:_pBleDevChar type:CBCharacteristicWriteWithResponse];
            }
            
            return;
        }
    }
    // Value for body sensor location received
    else if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A38"]])
    {
        NSData * updatedValue = characteristic.value;
        uint8_t* dataPointer = (uint8_t*)[updatedValue bytes];
        if(dataPointer)
        {
            uint8_t location = dataPointer[0];
            NSString*  locationString;
            switch (location)
            {
                case 0:
                    locationString = @"Other";
                    break;
                case 1:
                    locationString = @"Chest";
                    break;
                case 2:
                    locationString = @"Wrist";
                    break;
                case 3:
                    locationString = @"Finger";
                    break;
                case 4:
                    locationString = @"Hand";
                    break;
                case 5:
                    locationString = @"Ear Lobe";
                    break;
                case 6:
                    locationString = @"Foot";
                    break;
                default:
                    locationString = @"Reserved";
                    break;
            }
            //NSLog(@"Body Sensor Location = %@ (%d)", locationString, location);
        }
    }
}

- (void) onMeasTimer
{
    if(_measTimer != nil) {
        [_measTimer invalidate];
        _measTimer = nil;
    }
    //rem for test and debug
    if(_pBleDevSvr == nil) {
        if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(onBleDevDiscoverTimeOut)]) {
            [_bleDelegate onBleDevDiscoverTimeOut];
        }
    }
}

- (void) addSavedDevice:(NSString*) sUuid tryConn:(BOOL)bConn type:(short)nTypeIdx
{
    if(!_bJustScanDev)
        [self stopMeas];
    
    _sCurtSelUuid = sUuid;
    //_sStoredPEUuid = sUuid;
    
    NSUserDefaults *userSetting = [NSUserDefaults standardUserDefaults];
    //delete old one
    if(nTypeIdx == 0) {
        [userSetting removeObjectForKey:_kStoredHMUuid];
        [userSetting setObject:nil forKey:_kStoredHMUuid];
    }
    if(nTypeIdx == 2) {
        [userSetting removeObjectForKey:_kStoredPEUuid];
        [userSetting setObject:nil forKey:_kStoredPEUuid];
    }
    [userSetting synchronize];
    
    NSArray			*storedDevices	= [[NSUserDefaults standardUserDefaults] arrayForKey:_kStoredHMUuid];
    NSMutableArray	*newDevices		= nil;
    CFStringRef		uuidString		= NULL;
    
    uuidString = (__bridge CFStringRef)sUuid;//CFUUIDCreateString(NULL, uuid);
    //if(![_sCurrUuId isEqual: (__bridge NSString *)uuidString])
    //return;
    
    if (storedDevices.count > 0 && ![storedDevices isKindOfClass:[NSArray class]]) {
        //NSLog(@"Can't find/create an array to store the uuid");
        return;
    }
    
    if([storedDevices containsObject:(__bridge NSString*)uuidString])
        return;
    
    newDevices = [NSMutableArray arrayWithArray:storedDevices];
    if (uuidString) {
        [newDevices addObject:(__bridge NSString*)uuidString];
        //CFRelease(uuidString);
    }
    
    /* Store */
    [userSetting setObject:newDevices forKey:(nTypeIdx == 2)? _kStoredPEUuid: _kStoredHMUuid];
    [userSetting synchronize];
    
    if(bConn) {
        _bAutoConnect = YES;
        _bConnBleDev = NO;
    
        [self connStoredBlePeripheral:nTypeIdx];
    }
}

- (BOOL) loadSavedDevice:(short)nTypeIdx
{
    _bAutoConnect = YES;
    _nDevType = nTypeIdx;
    if(nTypeIdx == 2)
        return NO;
    
    NSString* sStoredUuid = [self getCurtStoredUuid:nTypeIdx];
    BOOL bOK = sStoredUuid != nil && sStoredUuid.length > 0;
    if(bOK) {
        _sCurtSelUuid = sStoredUuid;
        //[self startMeas:nil];
        //bOK = [self connStoredBlePeripheral:nTypeIdx];
        [self startMeas:nil];
    }
    //_bLoadSavedBleDev = bOK;
    return bOK;
}

- (BOOL) connStoredBlePeripheral:(short)nTypeIdx
{
    CBPeripheral* aPeripheral = [self getCurtStorePeripheral: nTypeIdx];
    if(aPeripheral != nil) {
        _pBleDevSvr = aPeripheral;
        _bAutoConnect = YES;
        _bConnBleDev = NO;
        [_bleMgr connectPeripheral:_pBleDevSvr options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:
                                                     CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
        if(![hrConntMonitors containsObject:_pBleDevSvr])
            [hrConntMonitors addObject:_pBleDevSvr];
        //[self stopScan];
    }
    
    
    return aPeripheral != nil;
}

- (CBPeripheral*) getCurtStorePeripheral:(short)nTypeIdx
{
    //NSArray* storedDevices = nil;
    NSUInteger nCount = hrConntMonitors.count;
    if(nCount == 0) {
        //storedDevices	= [[NSUserDefaults standardUserDefaults] arrayForKey:(nTypeIdx==2)?_kStoredPEUuid: _kStoredHMUuid];
        //nCount = storedDevices.count;
        return nil;
    }
    NSString* sSelUuid = [self getCurtStoredUuid: nTypeIdx];
    if(sSelUuid.length == 0)
        return nil;
    
    CBPeripheral* pCurtPeripheral = nil;
    for(NSInteger i=0; i<nCount; i++) {
        CBPeripheral* pSelPeripheral = nil;
        pSelPeripheral = [self listBleDev:i];
        NSString* sPerUuid = pSelPeripheral.identifier.UUIDString;
        if([sSelUuid isEqualToString:sPerUuid]) {
            pCurtPeripheral = pSelPeripheral;
            break;
        }
    }
    return pCurtPeripheral;// nCount > 0;
    
}

- (NSString*) getCurtStoredUuid:(short)nTypeIdx
{
    ///if(_sStoredPEUuid.length > 0)
        //return _sStoredPEUuid;
    if(_sCurtSelUuid.length > 0)
        return _sCurtSelUuid;
    
    NSArray	*storedDevices	= [[NSUserDefaults standardUserDefaults] arrayForKey:(nTypeIdx==2)?_kStoredPEUuid: _kStoredHMUuid];
    if(storedDevices == nil || storedDevices.count == 0)
       return nil;
       
    for (id deviceUUIDString in storedDevices) {
        if (![deviceUUIDString isKindOfClass:[NSString class]])
            continue;
        
        _sCurtSelUuid = deviceUUIDString;
        ///if(nTypeIdx == 2)
            //_sStoredPEUuid = deviceUUIDString;
        //if(_sStoredPEUuid.length > 0) {
            //break;
        //}
    }
    return _sCurtSelUuid;
}

//- (void) sendDataToBLeDev:(CBCharacteristic*)aChar data:(NSData*)valData type:(CBCharacteristicWriteType)hdType;
- (void) sendDataToBleDev:(CBCharacteristic*)aChar data:(NSData*) valData type:(CBCharacteristicWriteType)hdType
{
    const uint8_t*  dBody = valData.bytes;
    _bBodyMale = dBody[8] == 1;
    _nBodyYear = (short)dBody[9];
    _fBodyHgt = (float)dBody[7];
    
    if(_pBleDevSvr != nil && aChar != nil)
        [_pBleDevSvr writeValue:valData forCharacteristic:aChar type:hdType];
    
     NSLog(@"write char point: %@", _pBleDevChar);
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    NSString* sError = error.description;
    if (_bleDelegate && [_bleDelegate respondsToSelector:@selector(recvedBleOthData:)]) {
        [_bleDelegate recvedBleOthData:sError];
    }
}

#pragma mark /*-- BLE dev matcch --*/
- (NSUInteger) connBLEDevCount
{
    return hrConntMonitors.count;
}

- (NSUInteger) connBLEDevCount:(NSString*)sNamePre
{
    NSUInteger nCount = 0;
    NSUInteger n = hrConntMonitors.count;
    for(NSUInteger i=0; i<n; i++) {
        CBPeripheral* pPheral = [hrConntMonitors objectAtIndex:i];
        NSString* sBleName = pPheral.name;
        if(sBleName != nil && [sBleName hasPrefix:sNamePre])
            nCount++;
    }
    return nCount;
}

- (CBPeripheral*) listBleDev:(NSInteger)nIdx
{
    if(nIdx > hrConntMonitors.count-1)
        return nil;
    return [hrConntMonitors objectAtIndex:nIdx];
}

- (void) retrievePeripherals:(NSArray *)peripheralUUID
{
    //[_bleMgr retrievePeripherals:peripheralUUID];
    [_bleMgr retrievePeripheralsWithIdentifiers:peripheralUUID];
    
    /*NSUUID *uuid = [[NSUUID alloc]initWithUUIDString:peripheralUUID];
     //where savedUUID is the string version of the NSUUID you've saved somewhere
     
     NSArray *peripherals = [_bleMgr retrievePeripheralsWithIdentifiers:@[uuid]];
     return peripherals;*/
}

- (void) cancelPeripheralConnection/*:(CBPeripheral *)peripheral*/
{
    [_bleMgr cancelPeripheralConnection:_pBleDevSvr];
    _pBleDevSvr = nil;
}

-(void) disablePedoSyncSvr
{
    if(_pPedoSyncSvr != nil)
        [_pPedoSyncSvr setNotifyValue:NO forCharacteristic:_pBleDevChar];
}

- (void) enableSyncChar:(CBCharacteristic*)pChar enable:(BOOL)bEnable
{
    //[_pPedoSyncSvr setNotifyValue:bEnable forCharacteristic:pChar];
    if(_pPedoSyncSvr != nil)
        [_pPedoSyncSvr setNotifyValue:bEnable forCharacteristic:_pBleDevChar];
    
}


@end
